///////////////////////////////////////////////////////////////////////////
// Copyright 2010 Arabic Game Developer Network, All rights reserved
// www.agd-online.com - info@agdn-online.com
//
// File: stateflow.cpp
// Description: High-level module for managing the flow of the game.
//
///////////////////////////////////////////////////////////////////////////

// This file is part of kvalleyX.
//
// kvalleyX is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// kvalleyX is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with kvalleyX.  If not, see <http://www.gnu.org/licenses/>.

#include "stateflow.h"

namespace CoreLib
{

/////////////////// Transition class implementation ///////////////////////////
Transition::Transition(GameStateDescriptor* src, GameStateDescriptor* dest)
{
	this->src.reset(src);
	this->dest.reset(dest);
}

inline const GameStateDescriptor* Transition::getSourceState() const
{
	return src.get();	// boost::scoped_ptr
}

inline const GameStateDescriptor* Transition::getDestinationState() const
{
	return dest.get();	// boost::scoped_ptr
}

/////////////////// StateFlow Class Implementation ////////////////////////////

const char* StateFlow::START_STATE = "start_state";

StateFlow::StateFlow() :
currentState(NULL)
{
}

StateFlow::~StateFlow()
{
// 	if (m_pCurrentState)
// 		delete m_pCurrentState;
}


////////////////////////////////////////////////////////////////////////////////
// Function Name : StateFlow::Update
//
// Purpose : Updates the state flow manager
// Params : None.
//
// Return Value : None.
////////////////////////////////////////////////////////////////////////////////
void StateFlow::update()
{
	currentState->update();
/*	if (m_pCurrentState && (m_iTransitionTime == -1))
	{
		GameState::FlowAction eAction = m_pCurrentState->Update();
		if (eAction == GameState::FlowTo_Continue)
			return;
		m_eNextFlowAction = eAction;
		if (m_pCurrentState->TransitionAtEnd())
		{
			m_iTransitionTime = kTransitionPeriod;
			return;
		}
	}
	
	if (m_iTransitionTime-- > 0)
		return; // Disable updates while transition is active
		
		m_iTransitionTime = -1;
	if (m_pCurrentState)
		delete m_pCurrentState;
	m_pCurrentState = NULL;
	
	// Create the next state
	
	switch (m_eNextFlowAction)
	{
		case GameState::FlowTo_Intro1:
			m_pCurrentState = new GameState_Intro1();
			break;
		case GameState::FlowTo_Intro2:
			m_pCurrentState = new GameState_Intro2();
			break;
		case GameState::FlowTo_Password:
			m_pCurrentState = new GameState_Password();
			break;
		case GameState::FlowTo_Credit:
			m_pCurrentState = new GameState_Credits();
			break;
		case GameState::FlowTo_Play:
		{
			STATS& stats = GameApp::Instance->Stats;
			GameState_Play *pState = new GameState_Play();
			m_pCurrentState = pState;
			bool bSuccess =
			pState->SetPyramid(g_aLevelNames[stats.iCurrentLevel],FlowData.
			eCurrentLevelStartMode,stats.iCurrentLevel <= stats.iLevelCleared);
			if (!bSuccess)
			{
				if (m_pCurrentState)
					delete m_pCurrentState;
				m_pCurrentState = NULL;
			}
		}
		break;
		case GameState::FlowTo_Map:
			m_pCurrentState = new GameState_Map();
			break;
		case GameState::FlowTo_Outro:
			m_pCurrentState = new GameState_Outro();
			break;
	}

	if (m_pCurrentState)
		m_pCurrentState->Update();
	*/
}

void StateFlow::render(void)
{
	/*if (!m_pCurrentState) return;
	m_pCurrentState->Render();
	
	// Draw black swipe if transitioning
	if (m_iTransitionTime < 0) return;
	
	int iSwipeAmount = (((m_iTransitionTime*100000)/kTransitionPeriod) *
	SCREEN_WIDTH) / 100000;
	CoreLib::SplashFill(0,0,0,SCREEN_HEIGHT,SCREEN_WIDTH-iSwipeAmount);
	*/
}

void StateFlow::start(void)
{
	///NOTE: this function should initialize the machine and set the start
	/// state as current and exit.
	///TODO: There could be event handling interfacing wiht the event manager.

	///TODO: exit if we're started already
	
	// get the start state
	GameStateDescriptor start(StateFlow::START_STATE);
	currentState.reset(createState(start));
	/*
	m_eNextFlowAction = GameState::FlowTo_Intro1;
	m_iTransitionTime = 0;
	FlowData.eCurrentLevelStartMode = Pyramid::Starting_Intro;
	STATS& stats = GameApp::Instance->Stats;
	stats.iCurrentLevel = 0;
	stats.iLevelCleared = -1;
	stats.iScore = 0;
	stats.iAttempts = 1;
	*/
}

void StateFlow::addTransition(GameStateDescriptor* src,
							  GameStateDescriptor* dest,
							   const StateEvent& event)
{
	StateEvent copyEvent = event;
	transitions.insert(copyEvent, new Transition(src, dest));
}

} // CoreLib namespace